using System;
using System.Collections.Generic;
using System.Text;
using SongsDB;
using System.IO;
using System.Net;

namespace com.savage.mmtoxbmcexporter
{
    class MusicFileInfo
    {
        private string m_pathName;

        public string PathName
        {
            get { return m_pathName; }
            set { m_pathName = value; }
        }
        private string m_artistName;

        public string ArtistName
        {
            get { return m_artistName; }
            set { m_artistName = value; }
        }
        private string m_songName;

        public string SongName
        {
            get { return m_songName; }
            set { m_songName = value; }
        }

        private int m_songLengthInMilliseconds;

        public int SongLengthInMilliseconds
        {
            get { return m_songLengthInMilliseconds; }
            set { m_songLengthInMilliseconds = value; }
        }
        public MusicFileInfo()
        {
        }

    }

    class XBMCMusicExporter
    {
        //List<ISDBPlaylist> m_playlistList;
        //List<string> m_m3uFileList;
       
        private string m_BaseDir;
        ISDBApplication m_app;
        string m_XboxHostname;
        string m_XboxUserName;
        string m_XboxPassword;
        RARUtils m_RARUtils;

        public XBMCMusicExporter(ISDBApplication app, string xboxHostname, string xboxUserName, string xboxPassword)
        {
            //m_playlistList = new List<ISDBPlaylist>();
            //m_m3uFileList = new List<string>();
            m_BaseDir = Path.Combine(Path.GetTempPath(), "XBMC");
            m_app = app;
            Directory.CreateDirectory(m_BaseDir);

            m_XboxHostname = xboxHostname;
            m_XboxUserName = xboxUserName;
            m_XboxPassword = xboxPassword;

            m_RARUtils = new RARUtils();
        }

        public void Export(List<ISDBPlaylist> playlistList, string targetMusicDirectory, string targetPlaylistDirectory)
        {
            foreach (ISDBPlaylist playlist in playlistList)
            {
                string rarFileName;
                List<MusicFileInfo> fileInfoList = CreateRARArchiveForPlaylist(playlist, out rarFileName);

                string m3uFileName = GenerateM3UFile(fileInfoList, Path.Combine(targetMusicDirectory, Path.GetFileName(rarFileName)));

                // now download rar file and m3u file to xbox....
                FTPUtils ftpUtils = new FTPUtils(m_XboxHostname, m_XboxUserName, m_XboxPassword);
                ftpUtils.UploadFile(rarFileName, targetMusicDirectory);
                ftpUtils.UploadFile(m3uFileName, targetPlaylistDirectory);

                File.Delete(rarFileName);
                File.Delete(m3uFileName);
            }
        }

        private List<MusicFileInfo> CreateRARArchiveForPlaylist(ISDBPlaylist playlist, out string archiveFileName)
        {
            List<MusicFileInfo> fileInfoList = new List<MusicFileInfo>();
            archiveFileName = Path.Combine(m_BaseDir, Xboxify(CorrectTitle(playlist.Title))) + ".rar";
            
            m_RARUtils.ArchivePath = archiveFileName;
            m_RARUtils.FilesToAdd.Clear();

            SDBSongList songList = playlist.Tracks;
            for (int i = 0; i < songList.Count; ++i)
            {
                SDBSongData song = songList.get_Item(i);

                m_RARUtils.FilesToAdd.Add(song.Path);
                MusicFileInfo fi = new MusicFileInfo();
                fi.PathName = Path.GetFileName(song.Path);
                fi.ArtistName = song.Artist.Name;
                fi.SongLengthInMilliseconds = song.SongLength;
                fi.SongName = song.Title;
                fileInfoList.Add(fi);
            }
            m_RARUtils.Execute();
            return fileInfoList;
        }

        private string GenerateM3UFile(List<MusicFileInfo> fileInfoList, string rarFilePath)
        {
            string playlistTitle = System.IO.Path.GetFileNameWithoutExtension(rarFilePath);
            string fileName = System.IO.Path.Combine(m_BaseDir, playlistTitle + ".m3u");
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fileName);
            sw.WriteLine("#EXTM3U");

            foreach (MusicFileInfo fi in fileInfoList)
            {
                string songName = string.Format("{0} - {1}", fi.ArtistName, fi.SongName);
                sw.WriteLine(string.Format("#EXTINF:{0},{1}", (int)(fi.SongLengthInMilliseconds / 1e3), songName));
                string songPath = "rar://" + EncodePath(rarFilePath) + "/" + fi.PathName;
                sw.WriteLine(songPath);

            }
            sw.Close();
            return fileName;
        }

        

        private string ReplaceRange(string path, int beginning, int end)
        {
            for (int i = beginning; i <= end; ++i )
            {
                string srchStr = new string((char)i, 1);
                path = path.Replace(srchStr, "%" + i.ToString("x"));
            }
            return path;
        }

        private string EncodePath(string path)
        {
            path = ReplaceRange(path, 0x25, 0x2F); // must do % first
            path = ReplaceRange(path, 0x20, 0x24);
            path = ReplaceRange(path, 0x3a, 0x40);
            path = ReplaceRange(path, 0x5b, 0x60);
            path = ReplaceRange(path, 0x7b, 0x7e);
            return path;
        }

        //public void Generate()
        //{
        //    AddPlaylists(m_app.get_PlaylistByTitle(""));
        //    GenerateM3UList();

        //    SendFilesToXbox(m_XboxURL, m_XboxUserName, m_XboxPassword);

        //}

        //private void SendFilesToXbox(string xboxURL, string xboxUserName, string xboxPassword)
        //{
        //    WebClient request = new WebClient();

        //    request.Credentials = new NetworkCredential(xboxUserName, xboxPassword);
        //    foreach (string file in m_m3uFileList)
        //    {
        //        try
        //        {
        //            string url = CombineURL(xboxURL, Xboxify(Path.GetFileName(file)));
        //            byte[] responseData = request.UploadFile(url, file);
        //            string responseString = System.Text.Encoding.UTF8.GetString(responseData);
        //            Console.WriteLine(responseString);
        //        }
        //        catch (WebException e)
        //        {
        //            Console.WriteLine(e.ToString());
        //        }
        //    }

        //}

        private string Xboxify(string name)
        {
            string newName = name.Replace("?", "");
            newName = name.Replace("=", "-");
            newName = name.Replace(",", "_");
            newName = name.Replace("+", "_");
            if (newName.Length > 38)
            {
                // truncate
                newName = newName.Substring(0, 38);
            }
            return newName;
        }

        private string CombineURL(string baseURL, string file)
        {
            if (!baseURL.EndsWith("/"))
            {
                baseURL += "/";
            }
            return baseURL + file;
        }

        //private void AddPlaylists(ISDBPlaylist parent)
        //{
        //    if (parent.Tracks.Count > 0)
        //    {
        //        m_playlistList.Add(parent);
        //    }
        //    SDBPlaylists childlists = parent.ChildPlaylists;
        //    for (int i = 0; i < childlists.Count; ++i)
        //    {
        //        AddPlaylists(childlists.get_Item(i));
        //    }
        //}

        //private void GenerateM3UList()
        //{
        //    foreach (ISDBPlaylist list in m_playlistList)
        //    {
        //        m_m3uFileList.Add(GenerateM3UFile(list));
        //    }
        //}

        public string GenerateM3UFile(ISDBPlaylist list, bool fixBackslashes, string replaceText, string replacerText)
        {
            string title = CorrectTitle(list.Title);
            string fileName = System.IO.Path.Combine(m_BaseDir, title + ".m3u");
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fileName);
            sw.WriteLine("#EXTM3U");
            ISDBSongList songList = list.Tracks;
            for (int i = 0; i < songList.Count; ++i)
            {
                SDBSongData song = songList.get_Item(i);
                string songName = System.IO.Path.GetFileNameWithoutExtension(song.Path);
                if (song.Title != null && song.Title != "")
                {
                    songName = song.Title;
                    string artist = song.Artist.Name;
                    if (artist != null && artist != "")
                    {
                        songName = string.Format("{0} - {1}", artist, songName);
                    }
                }

                sw.WriteLine(string.Format("#EXTINF:{0},{1}", (int)(song.SongLength / 1e3), songName));
                string path = song.Path;
                if (replaceText != null && replacerText != null)
                {
                    path = GetCorrectedPath(path, replaceText, replacerText);
                }
                if (fixBackslashes)
                {
                    path = this.fixBackslashes(path);
                }
                sw.WriteLine(path);
            }
            sw.Close();
            return fileName;
        }

        //public void SendFileToXbox(string localFileName, 

        private string CorrectTitle(string title)
        {
            return m_app.Tools.FileSystem.CorrectFilename(title);
        }

        private string fixBackslashes(string path)
        {
            return path.Replace("\\", "/");
        }

        private string GetCorrectedPath(string path, string replaceText, string replacerText)
        {
            return path.Replace(replaceText, replacerText);
        }


    }
}
